<template>
  <div class="main" ref="ref_main">
    <canvas ref="ref_three"/>
  </div>
</template>

<script setup lang="ts">
import {getCurrentInstance, onMounted, reactive, ref} from "vue";
import * as THREE from 'three'
// 导入轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
// 导入gui调试开发
import {GUI} from 'three/examples/jsm/libs/lil-gui.module.min.js'

let scene: any = null
const {proxy} = getCurrentInstance()
const state: any = reactive({
  animate: true,
  controlData: {
    number: 0.01,
    color: '#000000',
    select: '1',
    boolean: false,
  },
  camera: null,
  renderer: null,
  bgCubeTexture: null,
  cubes: {},
  materials: {},
})
const ref_three = ref()
const ref_main = ref()
const initGUI = () => {
  // 创建GUI
  const gui = new GUI();
  gui.add(state.controlData,"number", 0.01, 1, 0.01)
  const one = gui.addFolder('第一')
  one.add(state.controlData,"number").min(0.01).max(1).step(0.01).name('数字')
  one.open()
  const two = gui.addFolder('第二')
  two.addColor(state.controlData,"color").name('颜色')
  two.add(state.controlData,"select", ['1', '2', '3']).name('下拉')
  two.add(state.controlData,"boolean").name('布尔')
  gui.domElement.id = 'cus-gui'
  ref_main.value.appendChild(gui.domElement)
}
const initScene = () => {
  // 场景
  scene = new THREE.Scene();
  // scene.background = new THREE.Color('rgba(224,110,110,0.3)');
  state.bgCubeTexture = new THREE.CubeTextureLoader().setPath(import.meta.env.BASE_URL + 'src/views/three/test/' ).load( [
    'bg_2.jpeg',
    'bg_2.jpeg',
    'bg_2.jpeg',
    'bg_2.jpeg',
    'bg_2.jpeg',
    'bg_2.jpeg',
  ] );  //  确保你加载或创建的每个cubemap面的宽度和高度完全相同
  scene.background = state.bgCubeTexture
  // 摄像机
  state.camera = new THREE.PerspectiveCamera( 75, ref_three.value.clientWidth / ref_three.value.clientHeight, 0.1, 1000 );
  state.camera.position.set(10,10,10)
  // 渲染器
  state.renderer = new THREE.WebGLRenderer({ canvas: ref_three.value, antialias: true });
  state.renderer.setSize(ref_three.value.clientWidth, ref_three.value.clientHeight);
  // 为了更清晰的看到物体的运动轨迹，可以添加坐标轴辅助对象AxesHelper
  // 红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.
  const axesHelper = new THREE.AxesHelper(10);
  scene.add(axesHelper);
  const cameraHelper = new THREE.CameraHelper( state.camera );
  scene.add(cameraHelper)

  // 监听窗口的变化
  window.addEventListener('resize',()=>{
    // 重置渲染器宽高比
    state.renderer.setSize(ref_three.value.clientWidth, ref_three.value.clientHeight);
    // 重置相机宽高比
    state.camera.aspect = ref_three.value.clientWidth / ref_three.value.clientHeight
    // 更新相机投影矩阵
    state.camera.updateProjectionMatrix()
  });

  initCube()
}
const initCube = () => {
  // 创建立方体
  const geometry = new THREE.BoxGeometry( 2, 2, 2 );
  // 创建纹理
  const texture = new THREE.TextureLoader().load(import.meta.env.BASE_URL + 'src/views/three/test/bg_1.png')
  // 添加材质（外观）
  const material = new THREE.MeshBasicMaterial( {
    // color: '#ffffff'
    map: texture
  } );
  // 创建网格
  const cube = new THREE.Mesh( geometry, material );
  cube.position.z = 3;
  scene.add( cube );
  state.cubes.cube1 = cube
  state.materials.material1 = material

  const geometry2 =  new THREE.SphereGeometry(2);
  const material2 = new THREE.MeshBasicMaterial( {
    // color: '#ffffff'
    envMap: state.bgCubeTexture
  } );
  const cube2 = new THREE.Mesh( geometry2, material2 );
  cube2.position.z = 3;
  cube2.position.y = 6;
  scene.add( cube2 );

  const geometry3 = new THREE.BufferGeometry();
  const vertices3 = new Float32Array([
    1, 2, 3,
    3, 2, 1,
    2, 1, 3,
  ])
  geometry3.setAttribute( 'position', new THREE.BufferAttribute( vertices3, 3 ) )
  const material3 = new THREE.MeshBasicMaterial( {
    color: 0xff0000,
    side: THREE.DoubleSide
  } );
  const cube3 = new THREE.Mesh( geometry3, material3 );
  scene.add( cube3 );


  const geometry4 = new THREE.BufferGeometry();
  const vertices4 = new Float32Array([
    -1, -2, -3,
    -3, -2, -1,
    -2, -1, -3,
    1, -1, 1,
  ])
  const indices = [
    0, 1, 2,
    2, 3, 0,
  ];

  geometry4.setIndex( indices );
  geometry4.setAttribute( 'position', new THREE.BufferAttribute( vertices4, 3 ) )
  const material4 = new THREE.MeshBasicMaterial( {
    color: 0xff0000,
    side: THREE.DoubleSide,
    wireframe: true
  } );
  const cube4 = new THREE.Mesh( geometry4, material4 );
  scene.add( cube4 );

  const geometry5 = new THREE.PlaneGeometry( 5, 5 );
  const uv = [
    0, 0.5,
    0.5, 0.5,
    0, 0,
    0.5, 0,
  ]
  geometry5.attributes.uv = new THREE.BufferAttribute(new Float32Array(uv), 2)
  const material5 = new THREE.MeshBasicMaterial( {
    map: texture,
    side: THREE.DoubleSide
  } );
  const cube5 = new THREE.Mesh( geometry5, material5 );
  cube5.position.x = 5;
  cube5.position.y = 5;
  scene.add( cube5 );

  initAnimate()
}
const initAnimate = () => {
  // 添加OrbitControls来控制摄像机
  const controls = new OrbitControls(state.camera, state.renderer.domElement);
  //设置一些属性
  controls.enableDamping  = true //启用阻尼（惯性）
  controls.dampingFactor = 0.05 //阻尼惯性有多大
  controls.autoRotate = false // 自动旋转
  controls.autoRotateSpeed = 1.0 //围绕目标旋转的速度将有多快

  const animate = () => {
    if (state.animate) {
      //注意：以上属性设置后，必须再动画循环里面调用update()更新控制器
      controls.update()
      requestAnimationFrame(animate)
      // cube.rotation.x += 0.01;
      // cube.rotation.y += 0.01;
      state.cubes.cube1.rotation.x += state.controlData.number
      state.cubes.cube1.rotation.y += state.controlData.number
      // cube.material.color = new THREE.Color(controlData.color)
      state.materials.material1.wireframe = state.controlData.boolean
      state.renderer?.render( scene, state.camera );
    } else {
      state.renderer?.render( scene, state.camera );
    }
  }
  animate()
}
onMounted(() => {
  initGUI()
  initScene()
})
</script>

<style lang="scss" scoped>
.main {
  width: 100%;
  height: 100%;
  position: relative;
  :deep(#cus-gui) {
    position: absolute;
    z-index: 22;
    top: 0;
    right: 0;
  }
  >canvas {
    width: 100%;
    height: 100%;
  }
}
</style>
